﻿using System;
using System.Linq;
using EndOfStreamException = System.IO.EndOfStreamException;

namespace CueMounter.DokanStructure {
	public class DokanCachedReadFile : DokanFile {
		DokanFile Target;
		byte[] Cache;

		public DokanCachedReadFile(DokanFile target, long cacheSize) {
			Name = target.Name;
			Target = target;
			cacheSize = Math.Min(target.Length, cacheSize);
			Cache = new byte[cacheSize];
			long fileRead = target.Read(0, Cache, 0, cacheSize);
			if(fileRead != cacheSize) {
				throw new EndOfStreamException();
			}
		}

		public override void Dispose() {
			Target.Dispose();
		}

		public override long Length {
			get {
				return Target.Length;
			}
			set
			{
				Target.Length = value;
			}
		}

		public override bool CanRead { get { return Target.CanRead; } }
		public override bool CanWrite { get { return Target.CanWrite; } }

		public override long Read(long fileOffset, byte[] buffer, long bufferOffset, long length) {
			long copied = 0;
			if(fileOffset < Cache.Length) {
				int cacheHit = (int)Math.Min(Cache.Length - fileOffset, length);
				Array.Copy(Cache, fileOffset, buffer, bufferOffset, cacheHit);
				fileOffset += cacheHit;
				bufferOffset += cacheHit;
				length -= cacheHit;
				copied += cacheHit;
			}
			if(length > 0) {
				copied += Target.Read(fileOffset, buffer, bufferOffset, length);
			}
			return copied;
		}

		public override long Write(long fileOffset, byte[] buffer, long bufferOffset, long length)
		{
			return Target.Write(fileOffset, buffer, bufferOffset, length);
		}
	}
}
